#pragma once
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <functional>
#include <sys/wait.h>
#include "Channel.hpp"
#include "task.hpp"
// 子进程读
// 父进程写
using work_t = std::function<void()>;
enum
{
    OK,
    USAGEERROR,
    PIPEERROR,
    FORKERROR
};
class processpool
{
public:
    processpool(int number, work_t w) : num(number), work(w)
    {
    }
    int InitProcessPool()
    {
        for (int i = 0; i < num; i++)
        {
            // 1.先创建管道
            int pipefd[2] = {0};
            int n = ::pipe(pipefd);
            if (n < 0)
                return PIPEERROR;
            // 2.创建子进程
            pid_t id = ::fork();
            if (id < 0)
                return FORKERROR;
            if (id == 0)
            {
                // 关闭历史wfd
                std::cout<<getpid()<<", history wfd: ";
                for (auto &c : channels)
                {
                    std::cout<<c.wfd()<<" ";
                    c.Close();
                }
                std::cout<<" done...."<<std::endl;
                // 子进程
                ::close(pipefd[1]);   // 关闭写端
                ::dup2(pipefd[0], 0); // 将读端重定向到标准输出,方便与work解耦
                work();
                exit(0); // 工作结束子进程退出
            }
            // 父进程
            ::close(pipefd[0]);
            channels.emplace_back(pipefd[1], id); // 父进程保存子进程信息
        }
        return OK;
    }
    void DeBug()
    {
        for (auto &c : channels)
        {
            std::cout << "channel: " << c.Name() << std::endl;
        }
    }
    // 2.分派任务
    void RotaTasks()
    {
        int num = 10;
        int who = 0;
        while (num--)
        {
            // 选择任务
            int task = tm.Select();
            // 选择进程
            Channel &channel = channels[who++];
            who %= channels.size();
            std::cout << "################" << std::endl;
            std::cout << "Send:" << task << " to " << channel.Name() << std::endl;
            std::cout << "################" << std::endl;
            std::cout << "剩余任务量：" << num << std::endl;
            channel.Send(task);
            sleep(1);
        }
    }
    // 3.回收进程池
    void CleanProcessPool()
    {
        // version 3
        for (auto &c : channels)
        {
            c.Close();
            std::cout << "child process quie success....." << std::endl;
            int rid = ::waitpid(c.id(), nullptr, 0);
            if (rid > 0)
                std::cout << c.id() << " ,child process wait sucess......" << std::endl;
        }
        // // version 2
        // for (int i = channels.size() - 1;i >= 0; i--)
        // {
        //     channels[i].Close();

        //     int rid = ::waitpid(channels[i].id(), nullptr, 0);
        //     if (rid > 0)
        //         std::cout <<channels[i].id()<<" ,child process wait sucess......"<<std::endl;
        // }
        // version 1
        //  // 3.关闭管道写入，读自动退出
        //  for (auto &c : channels)
        //  {
        //      c.Close();
        //  }
        //  // 4.回收进程
        //  for (auto &c : channels)
        //  {
        //      int status;
        //      int rid = ::waitpid(c.id(), &status, 0);
        //      if (rid > 0)
        //          std::cout << "退出码:" << WEXITSTATUS(status) << std::endl;
        //  }
    }

private:
    std::vector<Channel> channels;
    int num;
    work_t work;
};
